package com.woate.wingframework.utils;

import com.woate.wingframework.annotations.runtime.version.Version;

import java.net.URL;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;

/**
 * 用于获取Java类的版本号
 */
public final class VersionUtil {

    private VersionUtil() {
    }


    private static final String VERSION = getVersion(VersionUtil.class, "1.0.0");

    static {
        // 检查是否存在重复的jar包
        VersionUtil.checkDuplicate(VersionUtil.class);
    }

    /**
     * 获取Version类的版本号
     *
     * @return
     */
    public static String getVersion() {
        return VERSION;
    }

    /**
     * 检查是否有指定资源
     *
     * @param path 资源路径
     * @return 存在返回真，不存在返回假
     */
    public static boolean hasResource(String path) {
        try {
            return VersionUtil.class.getClassLoader().getResource(path) != null;
        } catch (Throwable t) {
            return false;
        }
    }

    /**
     * 获取特定类的版本号,如果无版本默认1.0.0<br/>
     *
     * @param cls 类对象
     * @return 类对象版本号
     * @see VersionUtil#getVersion(Class, String)
     */
    public static String getVersion(Class<?> cls) {
        return getVersion(cls, "1.0.0");
    }

    /**
     * 获取特定类的版本号<br/>
     * <li>
     * <ol>从Version注解获取版本号</ol>
     * <ol>查找MANIFEST.MF规范中的版本号，如过存在实现版本号，则返回实现版本号</ol>
     * <ol>查找MANIFEST.MF规范中的版本号，如过存在规范版本号，则返回规范版本号</ol>
     * <ol>从Jar路径获取版本号</ol>
     * </li>
     *
     * @param cls            类对象
     * @param defaultVersion 默认版本号
     * @return 类对象版本号
     */
    public static String getVersion(Class<?> cls, String defaultVersion) {
        try {
            String version = null;
            Version versionAnn = cls.getAnnotation(Version.class);
            if (versionAnn != null && versionAnn.value() != null && !versionAnn.value().isEmpty()) {
                version = versionAnn.value();
            }
            // 查找MANIFEST.MF规范中的版本号
            if (version == null || version.length() == 0) {
                version = cls.getPackage().getImplementationVersion();
            }
            if (version == null || version.length() == 0) {
                version = cls.getPackage().getSpecificationVersion();
            }
            if (version == null || version.length() == 0) {
                // 如果规范中没有版本号，基于jar包名获取版本号
                String file = cls.getProtectionDomain().getCodeSource().getLocation().getFile();
                if (file != null && file.length() > 0 && file.endsWith(".jar")) {
                    file = file.substring(0, file.length() - 4);
                    int i = file.lastIndexOf('/');
                    if (i >= 0) {
                        file = file.substring(i + 1);
                    }
                    i = file.indexOf("-");
                    if (i >= 0) {
                        file = file.substring(i + 1);
                    }
                    while (file.length() > 0 && !Character.isDigit(file.charAt(0))) {
                        i = file.indexOf("-");
                        if (i >= 0) {
                            file = file.substring(i + 1);
                        } else {
                            break;
                        }
                    }
                    version = file;
                }
            }
            // 返回版本号，如果为空返回缺省版本号
            return version == null || version.length() == 0 ? defaultVersion : version;
        } catch (Throwable e) { // 防御性容错
            // 忽略异常，返回缺省版本号
//            e.printStackTrace();
            return defaultVersion;
        }
    }

    /**
     * 检查指定的路径资源是否存在重复
     *
     * @param cls
     */
    public static void checkDuplicate(Class<?> cls) {
        checkDuplicate(cls.getName().replace('.', '/') + ".class");
    }

    /**
     * 检查指定的路径资源是否存在重复
     *
     * @param path
     */
    public static void checkDuplicate(String path) {
        try {
            // 在ClassPath搜文件
            Enumeration<URL> urls = Thread.currentThread().getContextClassLoader().getResources(path);
            Set<String> files = new HashSet<String>();
            while (urls.hasMoreElements()) {
                URL url = urls.nextElement();
                if (url != null) {
                    String file = url.getFile();
                    if (file != null && file.length() > 0) {
                        files.add(file);
                    }
                }
            }
            // 如果有多个，就表示重复
            if (files.size() > 1) {
                System.out.println("Duplicate class " + path + " in " + files.size() + " jar " + files);
            }
        } catch (Throwable e) { // 防御性容错
            e.printStackTrace();
        }
    }

}